﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using StockShark.Models;

namespace StockShark.BusinessModels
{
    public class InstrumentsUpdater
    {
        public StockSharkDB db = new StockSharkDB();
        public StockQuotesParser Parser;

        public InstrumentsUpdater() 
        {
            Parser = new StockQuotesParser();
        }

        /// <summary>
        /// Metoda służąca do uaktualniania notowań giełdowych
        /// </summary>
        /// <returns>1 - poprawnie przeprowadzona aktualizacja, 0 - dane aktualne, więc aktualizacja nie jest
        /// przeprowadzana, -1 - błąd aktualizacji; DO USTALENIA</returns>
        public int Update()
        {
            if (!GameProperties.MarketOpen()) 
            {
                return 0;
            }

            int value = Parser.Parse();
            /*
             -1 - błędne parsowanie, dane nie będą aktualizowane
              0 - aktualizacja wszystkich notowań oprócz jednolitych
              1 - aktualizacja wszystkich notowań
             */
            switch (value) 
            {
                case -1:
                    break;

                case 0:
                    UpdateContinuousIndexes();
                    UpdateContinuousShares();
                    UpdateNewConnectIndexes();
                    UpdateNewConnectShares();
                    UpdateMaterials();
                    UpdateCurrencies();
                    TradeCenter.ExecuteTransactions(true, false, true, true);
                    break;

                case 1:
                    UpdateContinuousIndexes();
                    UpdateContinuousShares();
                    UpdateNewConnectIndexes();
                    UpdateNewConnectShares();
                    UpdateMaterials();
                    UpdateCurrencies();
                    UpdateUniformShares();
                    TradeCenter.ExecuteTransactions(true, true, true, true);
                    break;
            };
            return value;
        }

        /// <summary>
        /// Metoda aktualizująca indeksy ciągłe
        /// </summary>
        /// <returns>1 - poprawnie przeprowadzona aktualizacja, 0 - dane aktualne, więc aktualizacja nie jest
        /// przeprowadzana, -1 - błąd aktualizacji</returns>
        public int UpdateContinuousIndexes()
        {
            int result = 0;     // wynik działania metody
            IEnumerable<Instrument> continuousIndexesTmp = from index in db.Instruments
                                                           where index.Market.Equals("GPW Rynek Główny")
                                                           select index;
            
            List<Index> indexesLst = new List<Index>();

            foreach (var item in continuousIndexesTmp)
            {
                if (item.GetType() == typeof(Index))
                {
                    indexesLst.Add((Index)item);
                }
            }

            /* brak połączenia z bazą danych */
            if (indexesLst.Count == 0) 
            {
                return -1;
            }

            foreach (Instrument item in Parser.ContinuousIndexesList) 
            {
                foreach (Index instr in indexesLst) 
                {
                    if (instr.Name.Equals(item.Name)) 
                    {
                        if (instr.CurrentPrice != item.CurrentPrice) 
                        {
                            instr.CurrentPrice = item.CurrentPrice;
                            db.Entry(instr).State = System.Data.EntityState.Modified;
                            result = 1;
                        }
                        indexesLst.Remove(instr);
                        break;
                    }
                }
            }

            if (result == 1) 
            {
                db.SaveChanges();
            }
            return result;
        }

        /// <summary>
        /// Metoda aktualizująca akcje ciągłe
        /// </summary>
        /// <returns>1 - poprawnie przeprowadzona aktualizacja, 0 - dane aktualne, więc aktualizacja nie jest
        /// przeprowadzana, -1 - błąd aktualizacji</returns>
        public int UpdateContinuousShares()
        {
            int result = 0;     // wynik działania metody
            IEnumerable<Instrument> continuousSharesTmp = from index in db.Instruments
                                                           where index.Market.Equals("GPW Rynek Główny")
                                                           select index;

            List<Share> sharesLst = new List<Share>();

            foreach (var item in continuousSharesTmp)
            {
                if (item.GetType() == typeof(Share))
                {
                    sharesLst.Add((Share)item);
                }
            }

            /* brak połączenia z bazą danych */
            if (sharesLst.Count == 0)
            {
                return -1;
            }

            foreach (Instrument item in Parser.ContinuousInstrumentsList)
            {
                foreach (Share instr in sharesLst)
                {
                    if (instr.Name.Equals(item.Name))
                    {
                        if (instr.CurrentPrice != item.CurrentPrice)
                        {
                            instr.CurrentPrice = item.CurrentPrice;
                            db.Entry(instr).State = System.Data.EntityState.Modified;
                            result = 1;
                        }
                        sharesLst.Remove(instr);
                        break;
                    }
                }
            }

            if (result == 1)
            {
                db.SaveChanges();
            }
            return result;
        }

        /// <summary>
        /// Metoda aktualizująca indeksy z NewConnect
        /// </summary>
        /// <returns>1 - poprawnie przeprowadzona aktualizacja, 0 - dane aktualne, więc aktualizacja nie jest
        /// przeprowadzana, -1 - błąd aktualizacji</returns>
        public int UpdateNewConnectIndexes()
        {
            int result = 0;     // wynik działania metody
            IEnumerable<Instrument> newConnectIndexesTmp = from index in db.Instruments
                                                           where index.Market.Equals("NewConnect")
                                                           select index;

            List<Index> indexesLst = new List<Index>();

            foreach (var item in newConnectIndexesTmp)
            {
                if (item.GetType() == typeof(Index))
                {
                    indexesLst.Add((Index)item);
                }
            }

            /* brak połączenia z bazą danych */
            if (indexesLst.Count == 0)
            {
                return -1;
            }

            foreach (Instrument item in Parser.NewConnectIndexesList)
            {
                foreach (Index instr in indexesLst)
                {
                    if (instr.Name.Equals(item.Name))
                    {
                        if (instr.CurrentPrice != item.CurrentPrice)
                        {
                            instr.CurrentPrice = item.CurrentPrice;
                            db.Entry(instr).State = System.Data.EntityState.Modified;
                            result = 1;
                        }
                        indexesLst.Remove(instr);
                        break;
                    }
                }
            }

            if (result == 1)
            {
                db.SaveChanges();
            }
            return result;
        }

        /// <summary>
        /// Metoda aktualizująca akcje z New Connect
        /// </summary>
        /// <returns>1 - poprawnie przeprowadzona aktualizacja, 0 - dane aktualne, więc aktualizacja nie jest
        /// przeprowadzana, -1 - błąd aktualizacji</returns>
        public int UpdateNewConnectShares()
        {
            int result = 0;     // wynik działania metody
            IEnumerable<Instrument> newConnectSharesTmp = from index in db.Instruments
                                                          where index.Market.Equals("NewConnect")
                                                          select index;

            List<Share> sharesLst = new List<Share>();

            foreach (var item in newConnectSharesTmp)
            {
                if (item.GetType() == typeof(Share))
                {
                    sharesLst.Add((Share)item);
                }
            }

            /* brak połączenia z bazą danych */
            if (sharesLst.Count == 0)
            {
                return -1;
            }

            foreach (Instrument item in Parser.NewConnectInstrumentsList)
            {
                foreach (Share instr in sharesLst)
                {
                    if (instr.Name.Equals(item.Name))
                    {
                        if (instr.CurrentPrice != item.CurrentPrice)
                        {
                            instr.CurrentPrice = item.CurrentPrice;
                            db.Entry(instr).State = System.Data.EntityState.Modified;
                            result = 1;
                        }
                        sharesLst.Remove(instr);
                        break;
                    }
                }
            }

            if (result == 1)
            {
                db.SaveChanges();
            }
            return result;
        }

        /// <summary>
        /// Metoda aktualizująca jednolite akcje
        /// </summary>
        /// <returns>1 - poprawnie przeprowadzona aktualizacja, 0 - dane aktualne, więc aktualizacja nie jest
        /// przeprowadzana, -1 - błąd aktualizacji</returns>
        public int UpdateUniformShares()
        {
            int result = 0;     // wynik działania metody
            IEnumerable<Instrument> uniformSharesTmp = from index in db.Instruments
                                                          where index.Market.Equals("GPW Rynek Główny")
                                                          select index;

            List<Share> sharesLst = new List<Share>();

            foreach (var item in uniformSharesTmp)
            {
                if (item.GetType() == typeof(Share) && ((StockShark.Models.Share)item).Fixing == true)
                {
                    sharesLst.Add((Share)item);
                }
            }

            /* brak połączenia z bazą danych */
            if (sharesLst.Count == 0)
            {
                return -1;
            }

            foreach (Instrument item in Parser.UniformInstrumentsList)
            {
                foreach (Share instr in sharesLst)
                {
                    if (instr.Name.Equals(item.Name))
                    {
                        if (instr.CurrentPrice != item.CurrentPrice)
                        {
                            instr.CurrentPrice = item.CurrentPrice;
                            db.Entry(instr).State = System.Data.EntityState.Modified;
                            result = 1;
                        }
                        sharesLst.Remove(instr);
                        break;
                    }
                }
            }

            if (result == 1)
            {
                db.SaveChanges();
            }
            return result;
        }

        /// <summary>
        /// Metoda aktualizująca surowce
        /// </summary>
        /// <returns>1 - poprawnie przeprowadzona aktualizacja, 0 - dane aktualne, więc aktualizacja nie jest
        /// przeprowadzana, -1 - błąd aktualizacji</returns>
        public int UpdateMaterials()
        {
            int result = 0;     // wynik działania metody
            IEnumerable<Instrument> materialsTmp = from index in db.Instruments
                                                   where index.Market != "GPW Rynek Główny" && index.Market != "Forex" && index.Market != "NewConnect"
                                                   select index;

            List<Material> materialsLst = new List<Material>();

            foreach (var item in materialsTmp)
            {
                if (item.GetType() == typeof(Material))
                {
                    materialsLst.Add((Material)item);
                }
            }

            /* brak połączenia z bazą danych */
            if (materialsLst.Count == 0)
            {
                return -1;
            }

            foreach (Instrument item in Parser.MaterialsList)
            {
                foreach (Material instr in materialsLst)
                {
                    if (instr.Name.Equals(item.Name))
                    {
                        if (instr.CurrentPrice != item.CurrentPrice)
                        {
                            instr.CurrentPrice = item.CurrentPrice;
                            db.Entry(instr).State = System.Data.EntityState.Modified;
                            result = 1;
                        }
                        materialsLst.Remove(instr);
                        break;
                    }
                }
            }

            if (result == 1)
            {
                db.SaveChanges();
            }
            return result;
        }

        /// <summary>
        /// Metoda aktualizująca waluty
        /// </summary>
        /// <returns>1 - poprawnie przeprowadzona aktualizacja, 0 - dane aktualne, więc aktualizacja nie jest
        /// przeprowadzana, -1 - błąd aktualizacji</returns>
        public int UpdateCurrencies()
        {
            int result = 0;     // wynik działania metody
            IEnumerable<Instrument> currenciesTmp = from index in db.Instruments
                                                   where index.Market == "Forex"
                                                   select index;

            List<Currency> currenciesLst = new List<Currency>();

            foreach (var item in currenciesTmp)
            {
                if (item.GetType() == typeof(Currency))
                {
                    currenciesLst.Add((Currency)item);
                }
            }

            /* brak połączenia z bazą danych */
            if (currenciesLst.Count == 0)
            {
                return -1;
            }

            foreach (Instrument item in Parser.CurrenciesList)
            {
                foreach (Currency instr in currenciesLst)
                {
                    if (instr.Name.Equals(item.Name))
                    {
                        if (instr.CurrentPrice != item.CurrentPrice)
                        {
                            instr.CurrentPrice = item.CurrentPrice;
                            db.Entry(instr).State = System.Data.EntityState.Modified;
                            result = 1;
                        }
                        currenciesLst.Remove(instr);
                        break;
                    }
                }
            }

            if (result == 1)
            {
                db.SaveChanges();
            }
            return result;
        }
    }
}
